﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Text;
using System.Runtime;
using System.Runtime.Serialization;

namespace PickGold.Util.Net
{
	/// <summary>
	/// 用于跨域的远程 TcpClient 的引用
	/// </summary>
	public class TcpRemote : MarshalByRefObject, ITcpRemote, IDisposable
	{
		private TcpClient _Client;

		/// <summary>
		/// 初始化 TcpRemote 类的新实例。
		/// </summary>
		public TcpRemote()
		{
			this._Client = new TcpClient();
		}

		/// <summary>
		/// 初始化 TcpRemote 类的新实例。
		/// </summary>
		/// <param name="client">访问套接字</param>
		public TcpRemote(TcpClient client)
		{
			this._Client = client;
		}

		/// <summary>
		/// 检查基础 Socket 是否存在，即 TcpClient.Client 不等于空。
		/// </summary>
		public bool HasClient
		{
			get
			{
				if (this._Client.Client == null)
					return false;

				return true;
			}
		}

		/// <summary>
		/// 获取本地终结点。
		/// </summary>
		public IPEndPoint LocalEndPoint
		{
			get
			{
				return this._Client.Client.LocalEndPoint as IPEndPoint;
			}
		}

		/// <summary>
		/// 获取远程终结点。
		/// </summary>
		public IPEndPoint RemoteEndPoint
		{
			get
			{
				return this._Client.Client.RemoteEndPoint as IPEndPoint;
			}
		}

		/// <summary>
		/// 获取一个值，该值指示 System.Net.Sockets.TcpClient 的基础 System.Net.Sockets.Socket 是否已连接到远程主机。
		/// </summary>
		public bool Connected
		{
			get
			{
				return this._Client.Connected;
			}
		}

		/// <summary>
		/// 将客户端连接到指定主机上的指定端口。
		/// </summary>
		/// <param name="hostname">要连接到的远程主机的 DNS 名。</param>
		/// <param name="port">要连接到的远程主机的端口号。</param>
		public void Connect(string hostname, int port)
		{
			this._Client.Connect(hostname, port);
		}

		/// <summary>
		/// 开始一个对远程主机连接的异步请求。远程主机由 System.Net.IPAddress 和端口号 (System.Int32) 指定。
		/// </summary>
		/// <param name="address">远程主机的 System.Net.IPAddress。</param>
		/// <param name="port">远程主机的端口号。</param>
		/// <param name="requestCallback">一个 System.AsyncCallback 委托，它引用操作完成时要调用的方法。</param>
		/// <param name="state">一个用户定义对象，其中包含连接操作的相关信息。操作完成时，此对象传递给了 requestCallback 委托。</param>
		/// <returns>一个 System.IAsyncResult 对象，它引用异步连接。</returns>
		public IAsyncResult BeginConnect(IPAddress address, int port, AsyncCallback requestCallback, object state)
		{
			return this._Client.BeginConnect(address, port, requestCallback, state);
		}

		/// <summary>
		/// 开始一个对远程主机连接的异步请求。远程主机由主机名 (System.String) 和端口号 (System.Int32) 指定。
		/// </summary>
		/// <param name="host">远程主机的名称。</param>
		/// <param name="port">远程主机的端口号。</param>
		/// <param name="requestCallback">一个 System.AsyncCallback 委托，它引用操作完成时要调用的方法。</param>
		/// <param name="state">一个用户定义对象，其中包含连接操作的相关信息。操作完成时，此对象传递给了 requestCallback 委托。</param>
		/// <returns>一个 System.IAsyncResult 对象，它引用异步连接。</returns>
		public IAsyncResult BeginConnect(string host, int port, AsyncCallback requestCallback, object state)
		{
			return this._Client.BeginConnect(host, port, requestCallback, state);
		}

		/// <summary>
		/// 异步接受传入的连接尝试。
		/// </summary>
		/// <param name="asyncResult">对 Overload:System.Net.Sockets.TcpClient.BeginConnect 的调用所返回的 System.IAsyncResult 对象。</param>
		public void EndConnect(IAsyncResult asyncResult)
		{
			this._Client.EndConnect(asyncResult);
		}

		/// <summary>
		/// 返回用于发送和接收数据的 System.Net.Sockets.NetworkStream。
		/// </summary>
		/// <returns>基础 System.Net.Sockets.NetworkStream。</returns>
		public NetworkStream GetStream()
		{
			return this._Client.GetStream();
		}

		/// <summary>
		/// 释放此 System.Net.Sockets.TcpClient 实例，并请求关闭基础 TCP 连接。
		/// </summary>
		public void Close()
		{
			this._Client.Close();
		}

		/// <summary>
		/// 执行与释放或重置非托管资源相关的应用程序定义的任务。
		/// </summary>
		public void Dispose()
		{
			var d = this._Client as IDisposable;
			d.Dispose();
		}
	}

	/// <summary>
	/// 用于跨域的远程 TcpClient 的引用
	/// </summary>
	public interface ITcpRemote : IDisposable
	{
		/// <summary>
		/// 检查基础 Socket 是否存在，即 TcpClient.Client 不等于空。
		/// </summary>
		bool HasClient { get; }

			/// <summary>
		/// 获取本地终结点。
		/// </summary>
		IPEndPoint LocalEndPoint { get; }

		/// <summary>
		/// 获取远程终结点。
		/// </summary>
		IPEndPoint RemoteEndPoint { get; }

		/// <summary>
		/// 获取一个值，该值指示 System.Net.Sockets.TcpClient 的基础 System.Net.Sockets.Socket 是否已连接到远程主机。
		/// </summary>
		bool Connected { get; }

		/// <summary>
		/// 将客户端连接到指定主机上的指定端口。
		/// </summary>
		/// <param name="hostname">要连接到的远程主机的 DNS 名。</param>
		/// <param name="port">要连接到的远程主机的端口号。</param>
		void Connect(string hostname, int port);

		/// <summary>
		/// 开始一个对远程主机连接的异步请求。远程主机由 System.Net.IPAddress 和端口号 (System.Int32) 指定。
		/// </summary>
		/// <param name="address">远程主机的 System.Net.IPAddress。</param>
		/// <param name="port">远程主机的端口号。</param>
		/// <param name="requestCallback">一个 System.AsyncCallback 委托，它引用操作完成时要调用的方法。</param>
		/// <param name="state">一个用户定义对象，其中包含连接操作的相关信息。操作完成时，此对象传递给了 requestCallback 委托。</param>
		/// <returns>一个 System.IAsyncResult 对象，它引用异步连接。</returns>
		IAsyncResult BeginConnect(IPAddress address, int port, AsyncCallback requestCallback, object state);

		/// <summary>
		/// 开始一个对远程主机连接的异步请求。远程主机由主机名 (System.String) 和端口号 (System.Int32) 指定。
		/// </summary>
		/// <param name="host">远程主机的名称。</param>
		/// <param name="port">远程主机的端口号。</param>
		/// <param name="requestCallback">一个 System.AsyncCallback 委托，它引用操作完成时要调用的方法。</param>
		/// <param name="state">一个用户定义对象，其中包含连接操作的相关信息。操作完成时，此对象传递给了 requestCallback 委托。</param>
		/// <returns>一个 System.IAsyncResult 对象，它引用异步连接。</returns>
		IAsyncResult BeginConnect(string host, int port, AsyncCallback requestCallback, object state);

		/// <summary>
		/// 异步接受传入的连接尝试。
		/// </summary>
		/// <param name="asyncResult">对 Overload:System.Net.Sockets.TcpClient.BeginConnect 的调用所返回的 System.IAsyncResult 对象。</param>
		void EndConnect(IAsyncResult asyncResult);

		/// <summary>
		/// 返回用于发送和接收数据的 System.Net.Sockets.NetworkStream。
		/// </summary>
		/// <returns>基础 System.Net.Sockets.NetworkStream。</returns>
		NetworkStream GetStream();

		/// <summary>
		/// 释放此 System.Net.Sockets.TcpClient 实例，并请求关闭基础 TCP 连接。
		/// </summary>
		void Close();
	}
}
